#include <iostream>
#include "httplib.h"
#include "ContactsException.h"
#include "add_contact.pb.h"

using namespace httplib;

#define CONTACTS_HOST "127.0.0.1"
#define CONTACTS_POST 8080

void menu()
{
    std::cout << "-----------------------------------------------------" << std::endl
              << "--------------- 请选择对通讯录的操作 ----------------" << std::endl
              << "------------------ 1、新增联系⼈ --------------------" << std::endl
              << "------------------ 2、删除联系⼈ --------------------" << std::endl
              << "------------------ 3、查看联系⼈列表 ----------------" << std::endl
              << "------------------ 4、查看联系⼈详细信息 ------------" << std::endl
              << "------------------ 0、退出 --------------------------" << std::endl
              << "-----------------------------------------------------" << std::endl;
}

void addContact();

int main()
{
    enum OPTION
    {
        QUIT = 0,
        ADD,
        DEL,
        FIND_ALL,
        FIND_ONE
    };

    while (true)
    {
        menu();
        std::cout << "--->请选择: ";
        int choose;
        std::cin >> choose;
        std::cin.ignore(256, '\n');
        try
        {
            switch (choose)
            {
            case OPTION::QUIT:
                std::cout << "--->程序退出" << std::endl;
                return 0;
            case OPTION::ADD:
                addContact();
                break;
            case OPTION::DEL:
                break;
            case OPTION::FIND_ALL:
                break;
            case OPTION::FIND_ONE:
                break;
            default:
                std::cout << "选择有误，请重新选择!" << std::endl;
                break;
            }
        }
        catch (const ContactsException &e)
        {
            std::cout << "--->操作通讯录时发生异常" << std::endl;
            std::cout << "--->异常信息: " << e.what() << std::endl;
        }
    }

    return 0;
}

void buildAddContactRequest(add_contact::AddContactRequest *req)
{
    std::cout << "--------------------新增联系人--------------------" << std::endl;
    std::cout << "请输入联系人的姓名: ";
    std::string name;
    std::getline(std::cin, name);
    req->set_name(name);

    std::cout << "请输入联系人的年龄: ";
    int age;
    std::cin >> age;
    req->set_age(age);
    std::cin.ignore(256, '\n');

    for (int i = 0;; i++)
    {
        std::cout << "请输入联系人的电话 " << i + 1 << " " << "(只输⼊回⻋完成电话新增): ";
        std::string number;
        std::getline(std::cin, number);
        if (number.empty())
            break;

        add_contact::AddContactRequest_Phone *phone = req->add_phone();
        phone->set_number(number);

        std::cout << "请输入该电话的类型 (1. 移动电话   2. 固定电话): ";
        int type;
        std::cin >> type;
        std::cin.ignore(256, '\n');
        switch (type)
        {
        case 1:
            phone->set_type(add_contact::AddContactRequest_Phone_PhoneType::AddContactRequest_Phone_PhoneType_MP);
            break;
        case 2:
            phone->set_type(add_contact::AddContactRequest_Phone_PhoneType::AddContactRequest_Phone_PhoneType_TEL);
            break;
        default:
            std::cout << "选择有误! " << std::endl;
            break;
        }
    }

    std::cout << "-------------------添加联系人成功------------------" << std::endl;
}

void addContact()
{
    Client client(CONTACTS_HOST, CONTACTS_POST);

    // 构造 req
    add_contact::AddContactRequest req;
    buildAddContactRequest(&req);

    // 序列化 req
    std::string req_str;
    if (!req.SerializeToString(&req_str))
    {
        throw ContactsException("AddContactRequest 序列化失败! ");
    }

    // 发起 post 调用
    Result res = client.Post("/contacts/add", req_str, "application/protobuf");
    if (!res)
    {
        std::string err_desc;
        err_desc.append("/contacts/add 链接失败！错误信息：").append(httplib::to_string(res.error()));
        throw ContactsException(err_desc);
    }

    // 反序列化 resp
    add_contact::AddContactResponse resp;
    bool parse = resp.ParseFromString(res->body);
    // 反序列化也失败了
    if (res->status != 200 && !parse)
    {
        std::string err_desc;
        err_desc.append("/contacts/add 调用失败! ").append(std::to_string(res->status)).append("(" + res->reason + ")");
        throw ContactsException(err_desc);
    }
    else if (res->status != 200)
    {
        std::string err_desc;
        err_desc.append("/contacts/add 调用失败! ").append(std::to_string(res->status)).append("(" + res->reason + ")").append("错误原因：" + resp.error_desc());
        throw ContactsException(err_desc);
    }
    else if (!resp.success())
    {
        std::string err_desc;
        err_desc.append("/contacts/add 结果异常! ").append(std::to_string(res->status)).append("(" + res->reason + ")").append("异常原因：" + resp.error_desc());
        throw ContactsException(err_desc);
    }

    // 结果打印
    std::cout << "新增联系人成功，联系人id：" << resp.uid() << std::endl;
}

// int main()
// {
//     Client client(CONTACTS_HOST, CONTACTS_POST);

//     Result res1 = client.Post("/test-post");
//     if(res1->status == 200) {
//         std::cout << "调用 post 成功!" << std::endl;
//     }

//     Result res2 = client.Get("/test-get");
//     if(res2->status == 200) {
//         std::cout << "调用 get 成功!" << std::endl;
//     }

//     return 0;
// }